/*  ----------------------------------------------------------------------------
 *  Arello Mobile
 *  Fast 3d Engine
 *  ----------------------------------------------------------------------------
 * Except where otherwise noted, this work is licensed under
 * http://creativecommons.org/licenses/by/3.0
 */

#ifndef __PLANE_H__
#define __PLANE_H__

#include "Vector3.h"
#include "Matrix4.h"
#include <lib3d/Math_lib3d.h>

namespace liba
{
namespace math
{

class Sphere;
class Box;

// The normal vector of a plane will always be normalized, when set.
// The offset of the plane is in direction of the plane normal.
// I.e.:
//
// ^
// |<-     offset     ->|
// |                    |normal  
// +---->               |-->    
//                      |
//                    Plane
//
// So the plane equation is normal*v - offset = 0
template< typename T >
class Plane
{
public:
	explicit Plane( const Vector3<T> & normal = Vector3<T>(0,0,1), const T & offset = 0 );
	Plane( const Vector3<T> & normal, const Vector3<T> & plane_point );

	bool intersects( const Sphere & sphere )const;
	bool intersects( const Box & box )const;
	T distance( const Vector3<T> & vec )const;

	void transform( const Matrix4<T> & transform );

	const Vector3<T> & get_normal()const
	{
		return normal;
	}
	const T & get_offset()const
	{
		return offset;
	}
	const Vector3<T> & get_plane_point()const
	{
		return plane_point;
	}
	const T distance2(const Vector3<T> & point) const
	{
		return Vector3<T>::dot(normal, point) + offset;
	}
	const T intersect_time(lib3d::Ray ray) const
	{
		return -distance2(ray.get_position()) / Vector3<T>::dot(normal, ray.get_direction());
	}
	const Vector3<T> intersect_point(lib3d::Ray ray) const
	{
		return ray.get_position() + ray.get_direction() * intersect_time(ray);
	}

	/* 
	* returns the component of v in the plane
	*/
	const Vector3<T> project_into_plane( const Vector3<T> & v )const;

private:
	Vector3<T> normal;
	Vector3<T> plane_point;
	T offset;
};

} // namespace math
} // namespace liba
using namespace liba;

#include "Plane.cpp"

#endif //__PLANE_H__